<?php
/**
 * bs多规格sku商城系统
 * ============================================================================
 * 版权所有 2024-2099 wltx666.com，并保留所有权利。
 * 网站地址: https://wltx666.com
 * ============================================================================
 * Author: 草上飞
 * Email: wltx@alipay168.cn
 * QQ: 2719875001
 * Date: 2024/12/26
 * 描述:
 */

namespace app\result\admin;

use app\model\admin\Admin;
use app\model\admin\AdminLoginLog;
use app\model\admin\AdminMenu;
use app\model\auto\Role;
use app\model\auto\RoleAuths;
use app\model\user\User;
use app\result\BaseResult;
use app\service\JWTService;

class AdminResult extends BaseResult
{
    public function __construct()
    {
        parent::__construct();
        $this->model = new Admin();
    }

    public function check_token($token, $field): array
    {
        if (cache('admin_token_' . md5($token))) {
            return self::error_return('无效的令牌');
        }
        try {
            $decode = (new JWTService())->decode($token);
        } catch (\Exception $e) {
            return self::error_return('token已过期', $e->getMessage());
        };

        if (isset($decoded->exp) && $decoded->exp < time()) {
            return self::error_return('token已过期');
        }

        // 检查'nbf'声明以确认当前时间是否在令牌生效之前
        if (isset($decoded->nbf) && $decoded->nbf > time()) {
            return self::error_return('token未生效，请等待一段时间再试');
        }

        $admin_id = $decode->sub;
        if (!$admin_id) {
            return self::error_return('token登录无效');
        }
        $data = (new Admin())->data_get(['admin_id' => $admin_id], $field);
        if (!$data) {
            return self::error_return('账号不存在');
        }
        return self::success_return('success', $data);
    }

    // 检查权限
    public function check_permission($role_id, $route)
    {
        if (!$role_id) {
            return true;
        }
        $menu_id = (new AdminMenu())->get_value(['path' => $route], 'id');
        if (!$menu_id) {
            return false;
        }
        return (new RoleAuths())->get_value(['role_id' => $role_id, 'menu_id' => $menu_id], 'id');
    }

    public function login($args): array
    {
        if (empty($args['account']) || empty($args['password'])) {
            return self::error_return('用户名或密码不能为空');
        }
        $admin = (new Admin())->data_get(['username' => $args['account']]);
        if (!$admin) {
            return self::error_return('账号不存在');
        }

        $errKey = 'admin_login_err_' . $args['account'];
        $errorCount = intval(cache($errKey));//错误次数
        $lockKey = $errKey . '_lock_time';
        $lockTime = cache($lockKey);
        if ($lockTime && $lockTime > time()) {
            return self::error_return('账号已锁定，请' . ($lockTime - time()) . '秒后重试', -1, $lockTime);
        }

        if ($admin['password'] != md5($args['password'] . $admin['salt'])) {
            cache($errKey, $errorCount + 1, 300);
            if ($errorCount > 5) {
                cache($lockKey, time() + 300, 300);
                return self::error_return('账号已锁定，请5分钟后重试', $lockTime);
            }
            return self::error_return('密码错误,您还可以重试' . (5 - $errorCount) . '次密码', -1);
        }
        cache($errKey, null);
        cache($lockKey, null);

        //10位随机数
        $salt = substr(md5(uniqid()), 0, 10);
        $pwd = md5($args['password'] . $salt);
        $up = [
            'password' => $pwd,
            'salt' => $salt,
            'last_login_ip' => request()->ip(),
            'last_login_time' => date('Y-m-d H:i:s'),
        ];
        $token = md5(uniqid() . time());
        (new Admin())->data_update(['admin_id' => $admin['admin_id']], $up);
        $expire_time = 86400 * 10;

        (new AdminLoginLog())->data_add([
            'admin_id' => $admin['admin_id'],
            'ip' => request()->ip(),
            'token' => $token,//登录token，兼容以后统一登录
            'expire' => $expire_time,//过期时间，方便以后统一登录
        ]);

        $payload = [
            "iss" => request()->domain(), // 使用当前请求域名作为签发者
            "aud" => request()->domain(), // 使用当前请求域名作为受众
            "iat" => time(), // 当前时间戳作为签发时间
            "nbf" => time(), // 0秒后生效
            "exp" => time() + $expire_time, // 有效期
            "sub" => $admin['admin_id'],
            "jti" => uniqid('', true), // 唯一的JWT ID
        ];

        $service = new JWTService();
        $token = $service->encode($payload);

        return self::success_return('登录成功', ['token' => $token]);
    }

    // 退出
    public function logout()
    {
        $token = request()->header('Authorization');
        $token = str_replace('Bearer ', '', $token);
        if ($token) {
            (new AdminLoginLog())->data_update(['token' => $token], ['expire' => 0]);
            cache('admin_token_' . md5($token), 1, 86400 * 7);
        }
        return self::success_return('退出成功');
    }

    public function save_data($args): array
    {
        $id = intval($args['admin_id'] ?? 0);
        if (empty($args['username'])) {
            return $this->error_return('请输入登录账号');
        }

        if ($id) {
            $data = $this->model->data_get(['admin_id' => $id]);
            if (!$data) {
                return $this->error_return('数据不存在');
            }
        } elseif (empty($args['password'])) {
            return $this->error_return('请输入登录密码');
        }

        if (!empty($args['password'])) {
            //弱密码判断
            if (strlen($args['password']) < 6) {
                return $this->error_return('密码长度不能小于6位');
            }
            //弱密码判断
            /*if (preg_match('/^[0-9]+$/', $args['password'])) {
                return $this->error_return('密码不能全是数字');
            }
            if (preg_match('/^[a-z]+$/', $args['password'])) {
                return $this->error_return('密码不能全是小写字母');
            }
            if (preg_match('/^[A-Z]+$/', $args['password'])) {
                return $this->error_return('密码不能全是大写字母');
            }
            if (preg_match('/^[0-9a-z]+$/', $args['password'])) {
                return $this->error_return('密码不能全是数字和字母');
            }
            if (preg_match('/^[A-Za-z]+$/', $args['password'])) {
                return $this->error_return('密码不能全是字母');
            }
            if (preg_match('/^[A-Z0-9]+$/', $args['password'])) {
                return $this->error_return('密码不能全是大写字母和数字');
            }*/
        }

        //登录账号不能重复
        if ($id) {
            $count = $this->model->data_count([['username', '=', $args['username']], ['admin_id', '<>', $id]]);
        } else {
            $count = $this->model->data_count(['username' => $args['username']]);
        }
        if ($count) {
            return $this->error_return('登录账号已存在');
        }

        $salt = substr(md5(uniqid()), 0, 10);


        $baseData = [
            'username' => $args['username'],
            'real_name' => $args['real_name'] ?? '',
            'password' => md5($args['password'] . $salt),
            'salt' => $salt,
            'is_disable' => !empty($args['is_disable']) ? 1 : 0,
            'remark' => $args['remark'] ?? '',
            'role_id' => intval($args['role_id'] ?? 0)
        ];
        if ($id) {
            $res = $this->model->data_update(['admin_id' => $id], $baseData);
            if (!$res) {
                return $this->success_return('数据未修改');
            }
        } else {
            $res = $this->model->data_add($baseData);
            if (!$res) {
                return $this->error_return('保存失败');
            }
        }
        admin_log('增改管理员', $args);
        return $this->success_return('保存成功');
    }


    // 表格列
    public function el_table_column(): array
    {
        return [
            ['prop' => 'admin_id', 'type' => 'text', 'label' => '管理员ID', 'minWidth' => '120', 'align' => 'center',],
            ['prop' => 'username', 'type' => 'text', 'label' => '登录账号', 'minWidth' => '120', 'align' => 'center',],
            ['prop' => 'role_name', 'type' => 'text', 'label' => '角色分组', 'minWidth' => '120', 'align' => 'center',],
            ['prop' => 'real_name', 'type' => 'text', 'label' => '真实姓名', 'minWidth' => '120', 'align' => 'center',],
            ['prop' => 'is_disable', 'type' => 'tags', 'label' => '是否禁用', 'minWidth' => '120', 'align' => 'center',
                'tags' => [
                    1 => ['label' => '禁用', 'color' => '', 'type' => 'success',],
                    0 => ['label' => '启用', 'color' => '', 'type' => 'success',],
                ]],
            ['prop' => 'remark', 'type' => 'text', 'label' => '备注', 'minWidth' => '120', 'align' => 'center',],
            ['prop' => 'last_login_ip', 'type' => 'text', 'label' => '最后登录IP', 'minWidth' => '120', 'align' => 'center',],
            ['prop' => 'last_login_time', 'type' => 'text', 'label' => '最后登录时间', 'minWidth' => '120', 'align' => 'center',],
            ['prop' => 'created_at', 'type' => 'text', 'label' => '创建时间', 'minWidth' => '120', 'align' => 'center',],
            ['prop' => 'updated_at', 'type' => 'text', 'label' => '更新时间', 'minWidth' => '120', 'align' => 'center',],
        ];
    }

    //列表搜索字段
    private function _searchField(): array
    {
        $roles = (new Role())->data_list_nopage([], 'role_id as value,role_name as label');
        $roles[] = ['label' => '超级管理', 'value' => 0];
        return [
            ['name' => 'username', 'label' => '登录账号', 'type' => 'input', 'placeholder' => '管理员用户名',],
            ['name' => 'real_name', 'label' => '真实姓名', 'type' => 'input', 'placeholder' => '真实姓名',],
            ['name' => 'is_disable', 'label' => '是否禁用', 'type' => 'select', 'placeholder' => '是否禁用', 'options' => [
                ['label' => '启用', 'value' => 0],
                ['label' => '禁用', 'value' => 1],
            ]],
            [
                'name' => 'role_id', 'label' => '角色分组',
                'type' => 'select',
                'placeholder' => '角色分组',
                'options' => $roles
            ]
        ];
    }

    // 获取公共条件限制
    private function _where($args = []): array
    {
        $where = [];
        $username = trim($args['username'] ?? '');
        $status = $args['is_disable'] ?? '';
        $real_name = trim($args['real_name'] ?? '');
        $role_id = $args['role_id'] ?? '';
        if ($username) {
            $where[] = ['username|real_name', 'like', '%' . trim($args['username']) . '%'];
        }
        if ($real_name) {
            $where[] = ['real_name', 'like', '%' . trim($args['real_name']) . '%'];
        }
        if (is_numeric($role_id)) {
            $where[] = ['role_id', '=', $role_id];
        }

        if (is_numeric($status)) {
            $where[] = ['is_disable', '=', $status];
        }
        return $where;
    }

    public function list($args = []): array
    {
        $page = intval($args['page'] ?? 1);
        $pageSize = intval($args['limit'] ?? 10);
        $sort_by = trim($args['sort_by'] ?? 'admin_id desc');
        $where = $this->_where($args);
        $total = $this->model->data_count($where);
        $data = $this->model->data_list($where, '*', $sort_by, $page, $pageSize);
        if ($data) {
            $modelRole = new Role();
            foreach ($data as &$item) {
                $item['role_name'] = $item['role_id'] == 0 ? '超级管理' : ($modelRole->get_value(['role_id' => $item['role_id']], 'role_name') ?? '');
            }
            unset($item);
        }
        return $this->success_return('success', [
            'total' => $total,
            'list' => $data,
            'el_table_column' => $this->el_table_column(),
            'search_fields' => $this->_searchField()
        ]);
    }

    public function get($args = []): array
    {
        $id = intval($args['id'] ?? 0);
        $data = $this->model->data_get(["admin_id" => $id]);
        if (!$data) {
            return $this->error_return('数据不存在');
        }
        return $this->success_return('success', [
            'info' => $data
        ]);
    }


    public function set_status($args): array
    {
        $id = intval($args['id'] ?? 0);
        if (!$id) {
            return $this->error_return('参数错误');
        }
        $data = $this->model->data_get(["admin_id" => $id], 'is_disable');
        if (!$data) {
            return $this->error_return('数据不存在');
        }
        $res = (new Admin())->data_update(["admin_id" => $id], ['is_disable' => $data['is_disable'] == 1 ? 0 : 1]);
        if (!$res) {
            return $this->error_return('修改状态失败');
        }
        admin_log('修改管理员状态', $args);
        return $this->success_return('保存成功');
    }

}
